home *** CD-ROM | disk | FTP | other *** search
/ Scene Storm / Scene Storm - Volume 1.iso / coding / c / rdb / rdb-informer.c < prev    next >
C/C++ Source or Header  |  1996-02-04  |  20KB  |  594 lines

  1. /* RDB-Informer V0.2
  2.  * Prints out information stored in the Rigid Disk Block of a device
  3.  *
  4.  * Written with MEmacs in September 1994 by
  5.  *
  6.  *               v
  7.  *     David Balazic
  8.  *     v
  9.  *     Centiba 39
  10.  *     69220 Lendava
  11.  *     Slovenija
  12.  *
  13.  * This program is FreeWare.
  14.  * You may spread it as you like, but leave my name noticed.
  15.  *
  16.  * Usage :
  17.  * > RDB-Informer [[DEVICE] <device>] [[UNIT] <unit-nr>]
  18.  *
  19.  * The default for DEVICE is 'scsi.device' and for UNIT '0'
  20.  *
  21.  * Examples :
  22.  * > RDB-Informer scsi.device unit 4
  23.  * > RDB-Informer gvpscsi.device unit 6
  24.  * > RDB-Informer unit 2                ; uses scsi.device unit 2
  25.  * > RDB-Informer evolution.device      ; uses evolution.device unit 0
  26.  *
  27.  */
  28.  
  29.  
  30. #include <clib/exec_protos.h>
  31. #include <clib/dos_protos.h>
  32.  
  33. #include <devices/trackdisk.h>
  34. #include <devices/hardblocks.h>
  35. #include <dos/filehandler.h>
  36. #include <dos/rdargs.h>
  37.  
  38. int OpenLibs(void);
  39. void CloseLibs(void);
  40. int OpenDev(void);
  41. void CloseDev(void);
  42. int ReadRDB(void);
  43. void ParseRDB(void);
  44. void PrintRDBFlags(ULONG);
  45. char *getstr(char *,char *,int);
  46. int SumOK(ULONG *);
  47. void ParseBADB(ULONG);
  48. void ParsePART(ULONG);
  49. void ParseFSHD(ULONG);
  50. void ParseDINI(ULONG);
  51. ULONG countBB(void);
  52. int readblok(ULONG *,ULONG,ULONG);
  53. char *BSTR2CSTR(UBYTE *,char *);
  54. void PrintPARTFlags(ULONG);
  55. void PrintPARTEnvironment(ULONG *);
  56. int countlen(ULONG);
  57. void partend(ULONG,int);
  58. void badend(ULONG,int);
  59. void fsend(ULONG,int);
  60.  
  61. struct DosLibrary *DOSBase;
  62. struct MsgPort *DevicePort;
  63. struct IOExtTD *scsiIO;
  64. struct RigidDiskBlock RDB;
  65. struct BadBlockBlock BBB;
  66. struct PartitionBlock PB;
  67. struct FileSysHeaderBlock FHB;
  68. struct LoadSegBlock LSB;
  69. struct RDArgs *args;
  70.  
  71. LONG argarray[]= {(LONG)"scsi.device",(LONG)NULL};
  72. int scsiopen;
  73. int RDBblok;
  74. char cbf[256];
  75. ULONG countbytes,countblocks;
  76. STRPTR verstring="\0$VER: RDB-Informer 0.2 (30.09.94)\x0a\x0d\0";
  77.  
  78. main()
  79. {
  80. LONG unitx=0;
  81. argarray[1]=(LONG)&unitx;
  82.  if(OpenLibs())
  83.  {
  84.   if(args=ReadArgs("DEVICE,UNIT/N",argarray,NULL))
  85.   {
  86.    if(OpenDev())
  87.    {
  88.     if(ReadRDB())
  89.     {
  90.      ParseRDB();
  91.     }else Printf("Rigid Disk Block of '%s' unit %ld not found.\n",argarray[0],*(LONG *)argarray[1]);
  92.    }else Printf("Can't open '%s' unit %ld!\n",argarray[0],*(LONG *)argarray[1]);
  93.   FreeArgs(args);
  94.   }else Printf("error in arguments\n");
  95.  CloseDev();
  96.  }else Printf("Can't open 'dos.library' version 36 !!!\n");
  97.  CloseLibs();
  98. }
  99.  
  100. int OpenLibs(void)
  101. {
  102. if( ! (DOSBase = (struct DosLibrary *) OpenLibrary(DOSNAME,36L) ) ) return FALSE;
  103. return TRUE;
  104. }
  105.  
  106. void CloseLibs(void)
  107. {
  108. if (DOSBase) CloseLibrary((struct Library *)DOSBase);
  109. }
  110.  
  111. int OpenDev(void)
  112. {
  113. if (DevicePort=CreateMsgPort())
  114. {
  115.  if(scsiIO=CreateIORequest(DevicePort,sizeof(struct IOExtTD)))
  116.  {
  117.   if(!OpenDevice((STRPTR)argarray[0],*((ULONG *)(argarray[1])),(struct IORequest *)scsiIO,0))
  118.   {
  119.    scsiopen=TRUE;
  120.    return TRUE;
  121.   }
  122.  }
  123. }
  124. scsiopen=FALSE;
  125. return FALSE;
  126. }
  127.  
  128. void CloseDev(void)
  129. {
  130. if(scsiopen)   CloseDevice((struct IORequest *)scsiIO);
  131. if(scsiIO)     DeleteIORequest(scsiIO);
  132. if(DevicePort) DeleteMsgPort(DevicePort);
  133. }
  134.  
  135. int ReadRDB(void)
  136. {
  137.  UBYTE buf[512];
  138.  int RDBfound=FALSE;
  139.  int blok=0,part=0;
  140.  
  141.  do
  142.  {
  143.   scsiIO->iotd_Req.io_Command=CMD_READ;
  144.   scsiIO->iotd_Req.io_Flags=0;
  145.   scsiIO->iotd_Req.io_Data=buf;
  146.   scsiIO->iotd_Req.io_Length=512;
  147.   scsiIO->iotd_Req.io_Offset=blok<<TD_SECSHIFT;
  148.  
  149.   DoIO((struct IORequest *)scsiIO);
  150.   RDBblok=blok;
  151.   if( ((struct RigidDiskBlock)buf).rdb_ID==IDNAME_RIGIDDISK )
  152.    RDBfound=TRUE;
  153.   blok++;
  154.   if(blok>RDB_LOCATION_LIMIT)break;
  155.  } while(!(RDBfound));
  156.  
  157.  if(RDBfound)
  158.  {
  159.   CopyMem(buf,&RDB,256);
  160.   return TRUE;
  161.  }else return FALSE;
  162. }
  163.  
  164. void ParseRDB(void)
  165. {
  166. Printf("Hard-blocks information of '%s' unit %ld\n\n",argarray[0],*(LONG *)argarray[1]);
  167. Printf("Rigid Disk Block found at block %ld",RDBblok);
  168. if(SumOK((ULONG *)&RDB)){
  169. Printf("  ---  CheckSum is OK.\n\n");
  170. Printf(" ID           = $%08lx = '%lc%lc%lc%lc'     block identifier\n",RDB.rdb_ID,
  171.      ( RDB.rdb_ID&0xff000000)>>24,(RDB.rdb_ID&0xff0000)>>16,
  172.      ( RDB.rdb_ID&0xff00)>>8,     (RDB.rdb_ID&0xff)   );
  173.  
  174. Printf(" SummedLongs  = $%08lx = %10ld size of RDB structure\n",RDB.rdb_SummedLongs,RDB.rdb_SummedLongs);
  175. Printf(" ChkSum       = $%08lx = %10ld block checksum\n",RDB.rdb_ChkSum,RDB.rdb_ChkSum);
  176. Printf(" HostID       = $%08lx = %10ld SCSI Target ID of host(controller)\n",RDB.rdb_HostID,RDB.rdb_HostID);
  177. Printf(" BlockBytes   = $%08lx = %10ld size of disk blocks\n",RDB.rdb_BlockBytes,RDB.rdb_BlockBytes);
  178. PrintRDBFlags(RDB.rdb_Flags);
  179.  
  180. Printf("\n --- Block list heads ($FFFFFFFF or -1 is none):\n");
  181. Printf(" BadBlockList      = $%08lx = %10ld optional bad block list\n",RDB.rdb_BadBlockList,RDB.rdb_BadBlockList);
  182. Printf(" PartitionList     = $%08lx = %10ld optional first partition block\n",RDB.rdb_PartitionList,RDB.rdb_PartitionList);
  183. Printf(" FileSysHeaderList = $%08lx = %10ld optional file system header block\n",RDB.rdb_FileSysHeaderList,RDB.rdb_FileSysHeaderList);
  184. Printf(" DriveInit         = $%08lx = %10ld optional drive-specific init code\n",RDB.rdb_DriveInit,RDB.rdb_DriveInit);
  185.  
  186. Printf("\n --- Physical drive characteristics:\n");
  187. Printf(" Cylinders    = $%08lx = %10ld number of drive cylinders\n",RDB.rdb_Cylinders,RDB.rdb_Cylinders);
  188. Printf(" Sectors      = $%08lx = %10ld sectors per track\n",RDB.rdb_Sectors,RDB.rdb_Sectors);
  189. Printf(" Heads        = $%08lx = %10ld number of drive heads\n",RDB.rdb_Heads,RDB.rdb_Heads);
  190. Printf(" Interleave   = $%08lx = %10ld interleave\n",RDB.rdb_Interleave,RDB.rdb_Interleave);
  191. Printf(" Park         = $%08lx = %10ld landing zone cylinder\n",RDB.rdb_Park,RDB.rdb_Park);
  192. Printf(" WritePreComp = $%08lx = %10ld starting cylinder: write precompensation\n",RDB.rdb_WritePreComp,RDB.rdb_WritePreComp);
  193. Printf(" ReducedWrite = $%08lx = %10ld starting cylinder: reduced write current\n",RDB.rdb_ReducedWrite,RDB.rdb_ReducedWrite);
  194. Printf(" StepRate     = $%08lx = %10ld drive step rate\n",RDB.rdb_StepRate,RDB.rdb_StepRate);
  195.  
  196. Printf("\n --- Logical drive characteristics\n");
  197. Printf(" RDBBlocksLo     = $%08lx = %10ld\n    low block of range reserved for these hardblocks\n",RDB.rdb_RDBBlocksLo,RDB.rdb_RDBBlocksLo);
  198. Printf(" RDBBlocksHi     = $%08lx = %10ld\n    high block of range reserved for these hardblocks\n",RDB.rdb_RDBBlocksHi,RDB.rdb_RDBBlocksHi);
  199. Printf(" LoCylinder      = $%08lx = %10ld\n    low cylinder of partitionable disk area\n",RDB.rdb_LoCylinder,RDB.rdb_LoCylinder);
  200. Printf(" HiCylinder      = $%08lx = %10ld\n    high cylinder of partitionable disk are\n",RDB.rdb_HiCylinder,RDB.rdb_HiCylinder);
  201. Printf(" CylBlocks       = $%08lx = %10ld number of blocks per cylinder\n",RDB.rdb_CylBlocks,RDB.rdb_CylBlocks);
  202. Printf(" AutoParkSeconds = $%08lx = %10ld zero means no autopark\n",RDB.rdb_AutoParkSeconds,RDB.rdb_AutoParkSeconds);
  203. Printf(" HighRDSKBlock   = $%08lx = %10ld highest block used by RDB\n",RDB.rdb_HighRDSKBlock,RDB.rdb_HighRDSKBlock);
  204.  
  205. Printf("\n --- Drive identification\n");
  206. Printf(" - Disk identification :");
  207. if ( RDB.rdb_Flags & RDBFF_DISKID)
  208. {
  209.  Printf("\n DiskVendor        = '%s'\n",getstr(RDB.rdb_DiskVendor,cbf,8));
  210.  Printf(  " DiskProduct       = '%s'\n",getstr(RDB.rdb_DiskProduct,cbf,16));
  211.  Printf(  " DiskRevision      = '%s'\n",getstr(RDB.rdb_DiskRevision,cbf,4));
  212. }else Printf(" *** not avaliable.\n");
  213. Printf("\n");
  214. Printf(" - Controller identification :");
  215. if ( RDB.rdb_Flags & RDBFF_CTRLRID)
  216. {
  217.  Printf("\n ControllerVendor  = '%s'\n",getstr(RDB.rdb_ControllerVendor,cbf,8));
  218.  Printf(  " ControllerProduct = '%s'\n",getstr(RDB.rdb_ControllerProduct,cbf,16));
  219.  Printf(  " ControllerRevision= '%s'\n",getstr(RDB.rdb_ControllerRevision,cbf,4));
  220. }else Printf("\n *** not avaliable.\n");
  221. Printf("\n");
  222. if(RDB.rdb_BlockBytes!=512)
  223. {
  224.  Printf("*** Block sizes other than 512 bytes not supported !!");
  225.  return;
  226. }
  227. if(RDB.rdb_BadBlockList!=0xffffffff) ParseBADB(RDB.rdb_BadBlockList);
  228. if(RDB.rdb_PartitionList!=0xffffffff) ParsePART(RDB.rdb_PartitionList);
  229. if(RDB.rdb_FileSysHeaderList!=0xffffffff) ParseFSHD(RDB.rdb_FileSysHeaderList);
  230. if(RDB.rdb_DriveInit!=0xffffffff) ParseDINI(RDB.rdb_DriveInit);
  231. }
  232. else
  233.  Printf("\n   *** CheckSum error !!\n");
  234.  
  235. }
  236.  
  237. void PrintRDBFlags(ULONG flags)
  238. {
  239. Printf(" Flags        = $%08lx =\n",flags);
  240.  
  241. if (flags & RDBFF_LAST)
  242. Printf("                RDBF_LAST       - Last drive on this controller\n");
  243. if (flags & RDBFF_LASTLUN)
  244. Printf("                RDBF_LASTLUN    - Last LUN on this SCSI-address\n");
  245. if (flags & RDBFF_LASTTID)
  246. Printf("                RDBF_LASTTID    - Last SCSI-address on this SCSI bus\n");
  247. if (flags & RDBFF_NORESELECT)
  248. Printf("                RDBF_NORESELECT - Does not support scsi reselection\n");
  249. else
  250. Printf("                                - Drive supports scsi reselection\n");
  251. if (flags & RDBFF_DISKID)
  252. Printf("                RDBF_DISKID     - RDB contains valid disk identification\n");
  253. if (flags & RDBFF_CTRLRID)
  254. Printf("                RDBF_CTRLRID    - RDB contains valid controller identification\n");
  255. if (flags & RDBFF_SYNCH)
  256. Printf("                RDBF_SYNCH      - Drive supports scsi synchronous mode\n");
  257. if ( flags & ~(RDBFF_LAST|RDBFF_LASTLUN|RDBFF_LASTTID|RDBFF_NORESELECT|RDBFF_DISKID|RDBFF_CTRLRID|RDBFF_SYNCH))
  258. Printf("                *** some unknown flags !!!!\n");
  259. }
  260.  
  261. char *getstr(char *from,char *to,int nr)
  262. {
  263. int cn=0;
  264. while ( ((to[cn]=from[cn])!=0)&&((cn+1)<nr)) cn++;
  265. to[cn+1]=0;
  266. return to;
  267. }
  268.  
  269. int SumOK(ULONG *p)
  270. {
  271. int i;
  272. LONG chk=0;
  273. ULONG nr=((struct RigidDiskBlock *)p)->rdb_SummedLongs;
  274.  
  275. if(nr>555) return FALSE;
  276.  
  277. for(i=0;i<nr;i++)
  278.    chk+=(*p++);
  279. if (chk) return FALSE;
  280. return TRUE;
  281. }
  282.  
  283. void ParseBADB(ULONG BADBblok)
  284. {
  285.  int res,blokerr=0;
  286.  ULONG bnr,allbad=0;
  287.  do
  288.  {
  289.   Printf("Bad Block Block at block %ld",BADBblok);
  290.   res=readblok((ULONG *)&BBB,BADBblok,IDNAME_BADBLOCK);
  291.   if(res==1){Printf("\n   *** Wrong block ID !!\n");badend(allbad,1);return;}
  292.   if(res==2){Printf("\n   *** CheckSum error !!\n");badend(allbad,1);return;}
  293.   if(res==3){Printf("\n   *** Read error !!\n");badend(allbad,1);return;}
  294.   if(res==0)
  295.   {
  296.    Printf("  ---  CheckSum is OK.\n\n");
  297.    bnr=countBB();
  298.    allbad+=bnr;
  299.    Printf(" This Bad Block Block contains %ld Bad Block replacements\n",bnr);
  300.    BADBblok=BBB.bbb_Next;
  301.   }
  302.   else
  303.   {
  304.    badend(allbad,1);
  305.    return;
  306.   }
  307.  }while(BADBblok!=0xffffffff);
  308.  badend(allbad,0);
  309. }
  310.  
  311. void badend(ULONG bad,int err)
  312. {
  313.  if(err)
  314.  Printf("*** There are some errors in Bad Block Blocks !!!\n");
  315.  Printf("There are total %ld valid Bad Block Replacements.\n\n",bad);
  316. }
  317.  
  318. int readblok(ULONG *buf,ULONG blkn,ULONG ident)
  319. {
  320.  scsiIO->iotd_Req.io_Command=CMD_READ;
  321.  scsiIO->iotd_Req.io_Flags=0;
  322.  scsiIO->iotd_Req.io_Data=buf;
  323.  scsiIO->iotd_Req.io_Length=512;
  324.  scsiIO->iotd_Req.io_Offset=blkn<<TD_SECSHIFT;
  325.  
  326.  DoIO((struct IORequest *)scsiIO);
  327.  if(scsiIO->iotd_Req.io_Error==0)
  328.  {
  329.   if( ((struct RigidDiskBlock *)buf)->rdb_ID==ident )
  330.   {
  331.    if(SumOK(buf))
  332.     return 0;
  333.    return 2;
  334.   }
  335.   else return 1;
  336.  }
  337.  else return 3;
  338. }
  339.  
  340. ULONG countBB(void)
  341. {
  342.  int c;
  343.  ULONG cnt=0;
  344.  for(c=0; (c<61)&&( ( ( ( &(BBB.bbb_BlockPairs[c]) ) - (&BBB) )>>2) < BBB.bbb_SummedLongs);c++)
  345.   if(BBB.bbb_BlockPairs[c].bbe_BadBlock!=0xffffffff)
  346.    cnt++;
  347.  return cnt;
  348. }
  349.  
  350. void ParsePART(ULONG PARTblok)
  351. {
  352.  int res;
  353.  ULONG allpart=0;
  354.  do
  355.  {
  356.   Printf("Partition Block at block %ld",PARTblok);
  357.   res=readblok((ULONG *)&PB,PARTblok,IDNAME_PARTITION);
  358.   if(res==1){Printf("\n   *** Wrong block ID !!\n");partend(allpart,1);return;}
  359.   if(res==2){Printf("\n   *** CheckSum error !!\n");partend(allpart,1);return;}
  360.   if(res==3){Printf("\n   *** Read error !!\n");partend(allpart,1);return;}
  361.   if(res==0)
  362.   {
  363.    allpart++;
  364.    Printf("  ---  CheckSum is OK.\n");
  365.    Printf(" Partition %s:\n",BSTR2CSTR(PB.pb_DriveName,cbf));
  366.    PrintPARTFlags(PB.pb_Flags);
  367.    Printf(" DevFlags       = $%08lx = %10ld Preferred flags for OpenDevice\n",PB.pb_DevFlags,PB.pb_DevFlags);
  368.    PrintPARTEnvironment(PB.pb_Environment);
  369.    Printf("\n");
  370.    PARTblok=PB.pb_Next;
  371.   }
  372.   else
  373.   {
  374.    partend(allpart,1);
  375.   }
  376.  }while(PARTblok!=0xffffffff);
  377.  partend(allpart,0);
  378. }
  379.  
  380. void partend(ULONG parts,int err)
  381. {
  382.  if(err)
  383.  Printf("*** There are some errors in Partition Blocks !!!\n");
  384.  Printf("There are total %ld valid partitions on this drive.\n\n",parts); 
  385. }
  386.  
  387.  
  388.  
  389. char *BSTR2CSTR(UBYTE *bstr,char* buf)
  390. {
  391. return getstr( (char *)(((ULONG)bstr)+1),buf,bstr[0]);
  392. }
  393.  
  394. void PrintPARTFlags(ULONG flags)
  395. {
  396. Printf(" Flags          = $%08lx =\n",flags);
  397.  
  398. if (flags & PBFF_BOOTABLE)
  399. Printf("                  PBF_BOOTABLE    - Partition is bootable\n");
  400. else
  401. Printf("                                  - Partition is not bootable\n");
  402. if (flags & PBFF_NOMOUNT)
  403. Printf("                  PBF_NOMOUNT     - Partition is not automaticaly mounted \n");
  404. else
  405. Printf("                                  - Partition is automaticaly mounted\n");
  406. if ( flags & ~(PBFF_BOOTABLE|PBFF_NOMOUNT))
  407. Printf("                   *** some unknown flags !!!!\n");
  408. }
  409.  
  410. void PrintPARTEnvironment(ULONG *inp)
  411. {
  412. struct DosEnvec *DE=(struct DosEnvec *)inp;
  413. ULONG siz=DE->de_TableSize;
  414. ULONG i=0;
  415.  
  416. Printf(" DosEnvec block with %ld entries\n",siz);
  417.  
  418. Printf(" SizeBlock      = $%08lx = %10ld block size in longwords\n",DE->de_SizeBlock,DE->de_SizeBlock);
  419. i++;
  420. if(i>=siz)return;
  421. Printf(" SecOrg         = $%08lx = %10ld not used\n",DE->de_SecOrg,DE->de_SecOrg);
  422. i++;
  423. if(i>=siz)return;
  424. Printf(" Surfaces       = $%08lx = %10ld number of heads\n",DE->de_Surfaces,DE->de_Surfaces);
  425. i++;
  426. if(i>=siz)return;
  427. Printf(" SectorPerBlock = $%08lx = %10ld not used; must be 1\n",DE->de_SectorPerBlock,DE->de_SectorPerBlock);
  428. i++;
  429. if(i>=siz)return;
  430. Printf(" BlocksPerTrack = $%08lx = %10ld number of blocks per track\n",DE->de_BlocksPerTrack,DE->de_BlocksPerTrack);
  431. i++;
  432. if(i>=siz)return;
  433. Printf(" Reserved       = $%08lx = %10ld DOS reserved blocks at start of partition\n",DE->de_Reserved,DE->de_Reserved);
  434. i++;
  435. if(i>=siz)return;
  436. Printf(" PreAlloc       = $%08lx = %10ld DOS reserved blocks at end of partition\n",DE->de_PreAlloc,DE->de_PreAlloc);
  437. i++;
  438. if(i>=siz)return;
  439. Printf(" Interleave     = $%08lx = %10ld (usually 0)\n",DE->de_Interleave,DE->de_Interleave);
  440. i++;
  441. if(i>=siz)return;
  442. Printf(" LowCyl         = $%08lx = %10ld starting cylinder\n",DE->de_LowCyl,DE->de_LowCyl);
  443. i++;
  444. if(i>=siz)return;
  445. Printf(" HighCyl        = $%08lx = %10ld ending cylinder\n",DE->de_HighCyl,DE->de_HighCyl);
  446. i++;
  447. if(i>=siz)return;
  448. Printf(" NumBuffers     = $%08lx = %10ld initial number of buffers\n",DE->de_NumBuffers,DE->de_NumBuffers);
  449. i++;
  450. if(i>=siz)return;
  451. Printf(" BufMemType     = $%08lx = %10ld type of memory for buffers\n",DE->de_BufMemType,DE->de_BufMemType);
  452. i++;
  453. if(i>=siz)return;
  454. Printf(" MaxTransfer    = $%08lx = %10ld max number of bytes to transfer at a time\n",DE->de_MaxTransfer,DE->de_MaxTransfer);
  455. i++;
  456. if(i>=siz)return;
  457. Printf(" Mask           = $%08lx = %10ld address mask to block out certain memory\n",DE->de_Mask,DE->de_Mask);
  458. i++;
  459. if(i>=siz)return;
  460. Printf(" BootPri        = $%08lx = %10ld boot priority for autoboot\n",DE->de_BootPri,DE->de_BootPri);
  461. i++;
  462. if(i>=siz)return;
  463. Printf(" DosType        = $%08lx = '%lc%lc%lc%lc'     HEX string showing filesystem type\n",DE->de_DosType,
  464.      ( DE->de_DosType&0xff000000)>>24,(DE->de_DosType&0xff0000)>>16,
  465.      ( DE->de_DosType&0xff00)>>8,     (DE->de_DosType&0xff)   );
  466. i++;
  467. if(i>=siz)return;
  468. Printf(" Baud           = $%08lx = %10ld baud rate for serial handler\n",DE->de_Baud,DE->de_Baud);
  469. i++;
  470. if(i>=siz)return;
  471. Printf(" Control        = $%08lx = %10ld control word for handler/filesystem\n",DE->de_Control,DE->de_Control);
  472. i++;
  473. if(i>=siz)return;
  474. Printf(" BootBlocks     = $%08lx = %10ld number of blocks containing boot code\n",DE->de_BootBlocks,DE->de_BootBlocks);
  475. i++;
  476. if(i>=siz)return;
  477. Printf(" *** %ld unknown entries !!\n",siz-i);
  478. }
  479.  
  480.  
  481.  
  482. void ParseFSHD(ULONG FSHDblok)
  483. {
  484.  int res;
  485.  ULONG allfs=0;
  486.  
  487.  do
  488.  {
  489.   Printf("File System Header Block at block %ld",FSHDblok);
  490.   res=readblok((ULONG *)&FHB,FSHDblok,IDNAME_FILESYSHEADER);
  491.   if(res==1){Printf("\n   *** Wrong block ID !!\n");fsend(allfs,1);return;}
  492.   if(res==2){Printf("\n   *** CheckSum error !!\n");fsend(allfs,1);return;}
  493.   if(res==3){Printf("\n   *** Read error !!\n");fsend(allfs,1);return;}
  494.   if(res==0)
  495.   {
  496.    allfs++;
  497.    Printf("  ---  CheckSum is OK.\n\n");
  498.    countbytes=countblocks=0;
  499.    if(countlen(FHB.fhb_SegListBlocks))
  500.    {
  501.     Printf(" Size      = $%08lx = %10ld bytes\n",countbytes,countbytes);
  502.     Printf(" Size      = $%08lx = %10ld blocks\n",countblocks,countblocks);
  503.     Printf(" Flags     = $%08lx = ?????\n",FHB.fhb_Flags);
  504.     Printf(" DosType   = $%08lx = '%lc%lc%lc%lc'\n",FHB.fhb_DosType,
  505.            ( FHB.fhb_DosType&0xff000000)>>24,(FHB.fhb_DosType&0xff0000)>>16,
  506.            ( FHB.fhb_DosType&0xff00)>>8,     (FHB.fhb_DosType&0xff)   );
  507.     Printf(" Version   = $%08lx = %5ld.%-5ld release version of this code\n",
  508.            FHB.fhb_Version,(FHB.fhb_Version&0xffff0000)>>16,FHB.fhb_Version&0xffff);
  509.     Printf(" PatchFlags= $%08lx = ?????\n",FHB.fhb_PatchFlags);
  510.     Printf(" Type      = $%08lx = %10ld device node type : zero\n",FHB.fhb_Type,FHB.fhb_Type);
  511.     Printf(" Task      = $%08lx = %10ld DOS task field : zero\n",FHB.fhb_Task,FHB.fhb_Task);
  512.     Printf(" Lock      = $%08lx = %10ld not used for devices : zero\n",FHB.fhb_Lock,FHB.fhb_Lock);
  513.     Printf(" Handler   = $%08lx = %10ld filename to loadseg : zero placeholder\n",FHB.fhb_Handler,FHB.fhb_Handler);
  514.     Printf(" StackSize = $%08lx = %10ld stacksize to use when starting task\n",FHB.fhb_StackSize,FHB.fhb_StackSize);
  515.     Printf(" Priority  = $%08lx = %10ld task priority when starting task\n",FHB.fhb_Priority,FHB.fhb_Priority);
  516.     Printf(" Startup   = $%08lx = %10ld startup message : zero placeholder\n",FHB.fhb_Startup,FHB.fhb_Startup);
  517.     Printf(" SegListBlocks=$%08lx=%10ld linked list of LoadSegBlocks\n",FHB.fhb_SegListBlocks,FHB.fhb_SegListBlocks);
  518.     Printf(" GlobalVec = $%08lx = %10ld BCPL global vector when starting task\n",FHB.fhb_GlobalVec,FHB.fhb_GlobalVec);
  519.     Printf(" Res2[0]   = $%08lx              reserved\n",FHB.fhb_Reserved2[0]);
  520.     Printf(" Res2[1]   = $%08lx              reserved\n",FHB.fhb_Reserved2[1]);
  521.     Printf(" Res2[2]   = $%08lx              reserved\n",FHB.fhb_Reserved2[2]);
  522.     Printf("\n");
  523.    }
  524.   FSHDblok=FHB.fhb_Next;
  525.   }
  526.   else
  527.   {
  528.    fsend(allfs,1);
  529.    return;
  530.   }
  531.  }while(FSHDblok!=0xffffffff);
  532.  fsend(allfs,0);
  533. }
  534.  
  535. void fsend(ULONG fs,int err)
  536. {
  537.  if(err)
  538.  Printf("*** There are some errors in File System Header Blocks !!!\n");
  539.  Printf("There are total %ld valid file systems stored on this drive.\n\n",fs);
  540. }
  541.  
  542. int countlen(ULONG LSEGblok)
  543. {
  544.  int res;
  545.  
  546.  do
  547.  {
  548.   res=readblok((ULONG *)&LSB,LSEGblok,IDNAME_LOADSEG);
  549.   if(res==1)
  550.   {
  551.    Printf("   *** Wrong block ID at block %ld.\n",LSEGblok);
  552.    Printf("   *** Expected LoadSegBlock (ID='LSEG'). Got ID = '%lc%lc%lc%lc'.\n",
  553.        ( RDB.rdb_ID&0xff000000)>>24,(RDB.rdb_ID&0xff0000)>>16,
  554.        ( RDB.rdb_ID&0xff00)>>8,     (RDB.rdb_ID&0xff)   );
  555.    return FALSE;
  556.   }
  557.   if(res==2)
  558.   {
  559.    Printf("   *** CheckSum error in block %ld (LoadSegBlock).\n",LSEGblok);
  560.    return FALSE;
  561.   }
  562.   if(res==3)
  563.   {
  564.    Printf("   *** Read error at block %ld (LoadSegBlock) !!\n");return FALSE;
  565.   }
  566.   if(res==0)
  567.   {
  568.    countblocks++;
  569.    countbytes+=(LSB.lsb_SummedLongs<<2)
  570.                -
  571.                (ULONG) &(((struct LoadSegBlock *)0L)->lsb_LoadData[0]);
  572.    LSEGblok=LSB.lsb_Next;
  573.   }
  574.   else
  575.    return FALSE;
  576.  }while(LSEGblok!=0xffffffff);
  577.  return TRUE;
  578. }
  579.  
  580.  
  581. void ParseDINI(ULONG DINIblok)
  582. {
  583.  int res;
  584.  
  585.  Printf("Dive Init Code starting at block %ld\n",DINIblok);
  586.  countbytes=countblocks=0;
  587.  if(countlen(DINIblok))
  588.  {
  589.   Printf(" Size      = $%08lx = %10ld bytes\n",countbytes,countbytes);
  590.   Printf(" Size      = $%08lx = %10ld blocks\n",countblocks,countblocks);
  591.  }
  592. }
  593.  
  594.